<template>
  <div>class学习</div>
</template>
 <!-- <script  src="./ClassTest.js"></script>  -->
<script setup lang="ts">
/**类*/
class Person {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  speak() {
    console.log(`我叫：${this.name},今年${this.age}岁`);
  }
}

/**定义一个类去继承Person类*/
class Student extends Person {
  grade: string; //年纪
  constructor(name: string, age: number, grade: string) {
    super(name, age); //这里写了自己的构造器就要用super去调用父类的构造器，不写就可以直接继承父类的构造器
    this.name = name;
    this.age = age;
    this.grade = grade;
  }
  //重写父类的speak方法
  override speak() {
    console.log(`我叫：${this.name},今年${this.age}岁，正在读${this.grade}`);
  }

  study() {
    console.log(`${this.name}正在努力学习中······`);
  }
}

let person = new Person("张三", 24);
person.speak(); //打印结果：我叫：张三,今年24岁

let student = new Student("顾清寒", 18, "大四下学期");
student.speak();
student.study();

//类的简写
class AbbreviationPerson {
  //使用修饰符直接可以不用写字段，也不用在构造器中赋值
  constructor(public name: string, public age: number) {}
  speak() {
    console.log(`我叫：${this.name},今年${this.age}岁`);
  }
}
let abbreviationPerson = new AbbreviationPerson("张三", 24);
abbreviationPerson.speak(); //打印结果：我叫：张三,今年24岁

//抽象类
abstract class ExpressDelivery {
  constructor(public weight: number) {}

  //抽象方法: 抽象方法不能写具体实现，只能写方法名和需要传入的参数，不能写方法体。 抽象方法子类必须重写
  abstract calculate(): number; //表示定义了一个名为calculate的抽象方法，返回值为number

  printFunc() {
    console.log(`包裹重量为：${this.weight}kg,运费为：${this.calculate()}元`);
  }
}

//继承ExpressDelivery抽象类
class SonExpressDelivery extends ExpressDelivery {
  constructor(weight: number, public price: number) {
    //width已经在父类写了public，所以在这里不需要在写修饰符了price是自己新加的，必须要写修饰符，否则不能用简写
    super(weight);
  }

  override calculate(): number {
    //这里写自己的计算逻辑
    return this.weight * this.price;
  }
}

let sonExpressDelivery = new SonExpressDelivery(10, 5);
sonExpressDelivery.printFunc(); //打印结果：包裹重量为：10kg,运费为：50元

/**接口*/
interface PersonInterface {
  name: string;
  age: number;
  speak(num: number): void; //不能写具体实现
}

interface PersonInterface2 {
  run(num: number): void; //不能写具体实现
}

//去实现PersonInterface和PersonInterface2接口（必须满足接口的格式）
class SonPersonInterface implements PersonInterface, PersonInterface2 {
  constructor(public name: string, public age: number, public weight: number) {}

  //重写的方法也必须满足接口的格式
  speak(height: number): void {
    console.log(
      `我叫：${this.name},今年${this.age}岁,身高${height},体重${this.weight}`
    );
  }
  run(num: number) {
    console.log(`跑了${num}分钟了`);
  }
}

let sonPersonInterface = new SonPersonInterface("张三", 24, 135);
sonPersonInterface.speak(180); //打印结果：我叫：张三,今年24岁,身高180,体重135

/**接口当作类型使用*/
interface UserInterface {
  name: string;
  readonly gender: string; //只读属性
  age?: number; //可选属性
  run(num: number): void;
}

interface UserInterface {
  weight: string;
}

const user: UserInterface = {
  name: "张三",
  gender: "男",
  weight: "65kg",
  run(n) {
    console.log(`奔跑了${n}米`);
  },
};
</script>